/** @file shader_mgr.h
    @brief Shader manager */

#ifndef G3_RES_SHADER_MGR_H
#define G3_RES_SHADER_MGR_H

#include "file/f_absfs.h"
#include "file/f_filehandler.h"

#include "singleton.h"

#include "res_shader.h"
#include "res_handle_mgr.h"

#include <map>
#include <set>
#include <vector>

namespace G3 {

/** @class SHADER_MANAGER
    @brief A shader manager singleton */
class SHADER_MANAGER: public SINGLETON <SHADER_MANAGER> {
	private:
        /** Vertex-shader filename index */
		std::map<std::string, H_VSHADER> VSNameIndex;
        /** Pixel-shader filename index */
		std::map<std::string, H_PSHADER> PSNameIndex;
		/** Vertex-shader handle manager */
		HANDLE_MANAGER<VERTEX_SHADER> VertexShaders;
		/** Pixel-shader handle manager */
		HANDLE_MANAGER<FRAGMENT_SHADER> PixelShaders;

	public:
        /**
            @brief A constructor
        */
		SHADER_MANAGER ();
        /**
            @brief A destructor
        */
		~SHADER_MANAGER ();

        /** Pointer to the log */
		LOG *Log;

        /**
            @brief Gets the filename of the shader
            @param[in] handle Shader handle
            @param[in] profile Shader profile
            @return Reference to the filename
        */
		std::string& GetShaderName (uint handle, SHADER_PROFILE profile);

        /**
            @brief Gets the shader by filename (and loads it if needed)
            @param[in] filename Reference to the path of the shader to be fetched
            @param[in] profile Shader profile
            @return Shader handle
        */
		uint GetShader (const string &filename, SHADER_PROFILE profile);

        /**
            @brief Gets a temporary pointer to the vertex shader class
            @param[in] Handle Vertex shader handle
            @return Pointer to the shader or NULL if it doesn't exist
        */
		boost::shared_ptr<VERTEX_SHADER> GetVSPointer (H_VSHADER Handle);

        /**
            @brief Gets a temporary pointer to the pixel shader class
            @param[in] Handle Pixel shader handle
            @return Pointer to the shader or NULL if it doesn't exist
        */
		boost::shared_ptr<FRAGMENT_SHADER> GetPSPointer (H_PSHADER Handle);

		/**
            @brief Gets the fileformat of a vertex shader
            @param[in] Handle Vertex shader handle
            @return The format \see SHADER_FORMAT
		*/
		SHADER_FORMAT GetVSFormat (H_VSHADER Handle);

		/**
            @brief Gets the fileformat of a pixel shader
            @param[in] Handle Pixel shader handle
            @return The format \see SHADER_FORMAT
		*/
		SHADER_FORMAT GetPSFormat (H_PSHADER Handle);

        /**
            @brief Gets the vertex shader identifier
            @param[in] Handle Vertex-shader handle
            @return Shader ID
        */
		uint GetVSID (H_VSHADER Handle);

        /**
            @brief Gets the pixel shader identifier
            @param[in] Handle Vertex-shader handle
            @return Shader ID
        */
		uint GetPSID (H_PSHADER Handle);

        /**
            @brief Applies a vertex shader
            @param[in] Handle Vertex shader handle
        */
		void ApplyVS (H_VSHADER Handle);

        /**
            @brief Applies a pixel shader
            @param[in] Handle pixel shader handle
        */
		void ApplyPS (H_PSHADER Handle);

        /**
            @brief UnApplies a vertex shader
            @param[in] Handle Vertex shader handle
        */
		void UnApplyVS (H_VSHADER Handle);

        /**
            @brief UnApplies a pixel shader
            @param[in] Handle pixel shader handle
        */
		void UnApplyPS (H_PSHADER Handle);

        /**
            @brief Deletes a vertex shader
            @param[in] Handle Vertex shader handle
        */
		void DeleteVS (H_VSHADER Handle);

        /**
            @brief Deletes a pixel shader
            @param[in] Handle pixel shader handle
        */
		void DeletePS (H_PSHADER Handle);

        /**
            @brief Dumps the whole shader manager into the log
        */
		void Dump ();
};

extern SHADER_MANAGER MainShaderManager;

}

#endif // G3_RES_SHADER_MGR_H
